package com.byit.controller;

import com.alibaba.fastjson.JSONObject;
import com.byit.EncryptType.MD5;
import com.byit.domain.AppUser;
import com.byit.domain.AppUserDevice;
import com.byit.domain.vo.AppUserVo;
import com.byit.dx.SendMessService;
import com.byit.enums.PromptInfo;
import com.byit.jgpush.JgPushExtra;
import com.byit.jgpush.JgPushService;
import com.byit.jwt.ann.JwtSessionController;
import com.byit.jwt.ann.JwtSessionOutController;
import com.byit.jwt.ann.JwtUser;
import com.byit.jwt.domain.JwtSession;
import com.byit.jwt.utils.JWTUtil;
import com.byit.msg.MessageResult;
import com.byit.service.IAppUserDeviceService;
import com.byit.service.IAppUserService;
import com.byit.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录接口
 *
 * @author wangx
 **/
@Slf4j
@RestController
@RequestMapping("/app")
public class AppLoginController {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IAppUserService appUserService;

    @Autowired
    private IAppUserDeviceService appUserDeviceService;

    @Autowired
    private JgPushService jgPushService;


    /**
     * 登录接口
     *
     * @param account      手机号或身份证号
     * @param password     密码
     * @param deviceId     激光推送标识
     * @param deviceName   设备名称
     * @param deviceSystem 设备型号
     * @return
     */
    @RequestMapping("/login")
    @JwtSessionController()
    public Object login(@RequestParam("account") String account, @RequestParam("password") String password,
                        @RequestParam("deviceId") String deviceId, @RequestParam("deviceName") String deviceName,
                        @RequestParam("deviceSystem") String deviceSystem) {
        // 加密
        String passwordMd5 = PasswordUtil.pwdEncrypt(password);
        if (account.length() != 11 && account.length() != 18) {
            return MessageResult.warpper(PromptInfo.ERROR_USER_LOGIN_PHONE);
        }

        // 查询手机号的用户
        AppUser user = appUserService.selectByPhoneOrIdCode(account);
        if (user == null) {
            return MessageResult.warpper(PromptInfo.ACCOUNT_NOT_EXISTS);
        }

        if (user.getStatus() == 0) {
            return MessageResult.warpper(PromptInfo.ERROR_USER_LOSS);
        }

        if (passwordMd5.equals(user.getPassword())) {
            String jwtToken = JWTUtil.sign(passwordMd5, JwtSession.builder()
                    .userId(user.getId())
                    .mobile(user.getPhone()));
            //下线提示
            sendOtherLogin(deviceId,user);

            user.setDeviceId(deviceId);
            user.setDeviceName(deviceName);
            user.setDeviceSystem(deviceSystem);
            user.setLoginTime(new Date());
            appUserService.updateById(user);

            JSONObject data = appUserService.getUserInfo(user.getId());
            data.put("token", jwtToken);

            AppUserDevice userDevice = new AppUserDevice();
            userDevice.setDeviceId(deviceId);
            userDevice.setDeviceName(deviceName);
            userDevice.setDeviceSystem(deviceSystem);
            userDevice.setLoginTime(new Date());
            userDevice.setUserId(user.getId());
            appUserDeviceService.insert(userDevice);
            return MessageResult.warpper("000", data, "登陆成功");
        }

        return MessageResult.warpper(PromptInfo.USER_ACCOUNT_PASS_ERROR);
    }

    /**
     * 获取手机验证码
     *
     * @param mobile
     * @param msgType 1注册 2登录 3忘记密码 4修改密码
     * @return
     */
    @RequestMapping("/gainCode")
    public Object gainCode(@RequestParam("mobile") String mobile, int msgType) {
        mobile = mobile.trim();
        if (null != mobile && !"".equals(mobile)) {
            if (mobile.length() != 11) {
                return MessageResult.warpper(PromptInfo.ERROR_USER_LOGIN_PHONE);
            }
            String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
            String key = "system:sjyzm:" + msgType + ":" + mobile;
            redisUtil.set(key, code, 180);
            JSONObject json = new JSONObject();
            json.put("code", code);
            boolean b = SendMessService.sendSmsForCode(code, mobile);
            if (b) {
                return MessageResult.warpper("000", null, "获取验证码成功");
            } else {
                return MessageResult.error();
            }
        }
        return MessageResult.warpper(PromptInfo.ERROR_MOBILE_NOT_EXISTS);
    }

    /**
     * 手机登录
     *
     * @param mobile       手机号
     * @param code         登录认证码
     * @param deviceId     激光推送标识
     * @param deviceName   设备名称
     * @param deviceSystem 设备型号
     * @return
     */
    @JwtSessionController()
    @RequestMapping("/smsLogin")
    public Object phoneLogin(@RequestParam("mobile") String mobile, @RequestParam("code") String code,
                             @RequestParam("deviceId") String deviceId, @RequestParam("deviceName") String deviceName,
                             @RequestParam("deviceSystem") String deviceSystem) {
        mobile = mobile.trim();
        if (mobile.length() != 11) {
            return MessageResult.warpper(PromptInfo.ERROR_USER_LOGIN_PHONE);
        }
        // 查询手机号的用户
        AppUser user = appUserService.selectByPhone(mobile);
        if (user == null) {
            return MessageResult.warpper(PromptInfo.ACCOUNT_NOT_EXISTS);
        }

        String pwd = user.getPassword();
        String key = "system:sjyzm:2:" + mobile;
        if (!redisUtil.hasKey(key)) {
            return MessageResult.warpper(PromptInfo.ERROR_SMS_CODE_NOT_EXISTS);
        }

        if (null != code && !"".equals(code.trim()) && code.equals(redisUtil.get(key))) {
            String jwtToken = JWTUtil.sign(pwd, JwtSession.builder()
                    .userId(user.getId())
                    .mobile(mobile));

            //下线提示
            sendOtherLogin(deviceId,user);
            user.setDeviceId(deviceId);
            user.setDeviceName(deviceName);
            user.setDeviceSystem(deviceSystem);
            user.setLoginTime(new Date());

            appUserService.updateById(user);
            return MessageResult.success(jwtToken);
        }
        return MessageResult.warpper(PromptInfo.VERIFY_CODE_ERROR);
    }

    /**
     * 忘记密码
     *
     * @param mobile
     * @param code
     * @param password
     * @return
     */
    @RequestMapping("/forget")
    public Object forgetPWD(@RequestParam("mobile") String mobile, @RequestParam("code") String code,
                            @RequestParam("password") String password) {

        if (mobile.length() != 11) {
            return MessageResult.warpper(PromptInfo.ERROR_USER_LOGIN_PHONE);
        }

        // 查询手机号的用户
        AppUser user = appUserService.selectByPhone(mobile);
        if (user == null) {
            return MessageResult.warpper(PromptInfo.ACCOUNT_NOT_EXISTS);
        }

        String key = "system:sjyzm:3:" + mobile;
        if (!redisUtil.hasKey(key)) {
            return MessageResult.warpper(PromptInfo.ERROR_SMS_CODE_NOT_EXISTS);
        }
        if (null != code && !"".equals(code.trim()) && code.equals(redisUtil.get(key))) {
            Map<String, Object> map = new HashMap<>();
            map.put("pwd", PasswordUtil.pwdEncrypt(password));
            map.put("phone", mobile);
            appUserService.updatePwdByPhone(map);
            return MessageResult.warpper("000", null, "重置密码成功");
        }
        return MessageResult.warpper(PromptInfo.VERIFY_CODE_ERROR);
    }

    /**
     * 修改密码
     *
     * @param passwordOld
     * @param passwordNew
     * @return
     */
    @RequestMapping("/modify/password")
    public Object modifyPWD(@JwtUser JwtSession session,
                            @RequestParam("passwordOld") String passwordOld,
                            @RequestParam("passwordNew") String passwordNew) {
        String passwordOldMd5 = PasswordUtil.pwdEncrypt(passwordOld);
        String passwordNewMd5 = PasswordUtil.pwdEncrypt(passwordNew);


        if (!session.isLogin()) { // 没有登录
            return MessageResult.warpper(PromptInfo.NOT_LOGGED);
        }
        Long userId = session.userId();
        if (userId == null) {
            return MessageResult.warpper(PromptInfo.NOT_LOGGED);
        }
        AppUser user = appUserService.selectById(userId);
        if (user == null) {
            return MessageResult.warpper(PromptInfo.NOT_LOGGED);
        }

        if (passwordOldMd5.equals(user.getPassword())) {

            Map<String, Object> map = new HashMap<>();
            map.put("password", passwordNewMd5);
            map.put("id", userId);
            map.put("modifyTime", new Date());
            appUserService.updatePassword(map);
            return MessageResult.warpper("000", null, "修改密码成功");
        }

        return MessageResult.warpper(PromptInfo.USER_ACCOUNT_PASS_ERROR);
    }

    /**
     * 会员用户注册
     *
     * @return
     */
    @RequestMapping("/register")
    public synchronized Object registerMember(AppUserVo vo) {
        AppUser appUser = new AppUser();
        appUser.setPassword(PasswordUtil.pwdEncrypt(vo.getPassword()));
        // 查询手机号的用户
        AppUser user = appUserService.selectByPhone(vo.getPhone());
        if (vo.getPhone().length() != 11) {
            return MessageResult.warpper(PromptInfo.ERROR_USER_LOGIN_PHONE);
        }
        if (null != user) {
            return MessageResult.warpper(PromptInfo.USER_IS_EXISTS);
        }
        String mobile = vo.getPhone().trim();

        String key = "system:sjyzm:1:" + mobile;
        if (!redisUtil.hasKey(key)) {
            return MessageResult.warpper(PromptInfo.ERROR_SMS_CODE_NOT_EXISTS);
        }

        if (!StringUtil.isEmpty(vo.getCode()) && vo.getCode().equals(redisUtil.get(key))) {
            appUser.setCreateTime(new Date());
            appUser.setPhone(vo.getPhone());
            appUser.setType(vo.getType());
            appUserService.insert(appUser);
            appUser.setAnonymous(UserNameUtil.getUserName());
            appUserService.updateById(appUser);
            if (appUser.getId() == null) {
                return MessageResult.error("注册失败，请重试！");
            }
            return MessageResult.warpper("000", null, "注册成功");
        }
        return MessageResult.warpper(PromptInfo.VERIFY_CODE_ERROR);
    }

    /**
     * 退出登录接口
     */
    @PostMapping("/login/out")
    @JwtSessionOutController
    public MessageResult loginOut(@JwtUser JwtSession jwtSession, HttpServletRequest request) {
        // 对JWT的认证字符串使用Redis存储，并赋予生命周期。
        return MessageResult.success(jwtSession);
    }

    /**
     * 提示用户在其他地方登录
     * @param appUser
     */
    private void sendOtherLogin(String deviceId,AppUser appUser){
        try {
            if (!deviceId.equals(appUser.getDeviceId())){
                JSONObject param = new JSONObject();
                String msg = "您的账号于" + DateUtil.getNowDate() + "在别处登录！";
                param.put("alias", MD5.md5(appUser.getDeviceId()+":"+appUser.getId()));
                param.put("content", msg);
                param.put("title", "下线通知");
                JgPushExtra extra = new JgPushExtra();
                extra.setType(1);
                extra.setLevel(1);
                extra.setContent(msg);
                extra.setTitle("下线通知");
                extra.setTime(new Date());
                extra.setSource("系统");
                param.put("data", extra);
                jgPushService.jpushAndroidIOSByaliasForMessage(param);
            }
        }catch (Exception e){
            log.error(e.getMessage());
        }
    }
}
